<?php

// Copyright 2019 Hackware SpA <human@hackware.cl>
// "Hackware Web Services Core" is released under the MIT License terms.

namespace Hawese\Tests;

use Illuminate\Http\Request;
use Laravel\Lumen\Testing\DatabaseTransactions;

class ControllerTest extends TestCase
{
    use DatabaseTransactions;

    public function setUp(): void
    {
        parent::setUp();

        $this->dumbController = new DumbController();
        $this->request = new Request();
    }

    public function testSingleResponse()
    {
        $obj = (object) ['any' => 'thing'];
        $this->assertEqualsCanonicalizing(
            $obj,
            $this->dumbController->singleResponse($obj)
        );
    }

    public function testCollectionResponsePage()
    {
        for ($i = 0; $i < 30; $i++) {
            (new DumbTableModel([
                'attr1' => bin2hex(random_bytes(12))
            ]))->insert();
        }

        $this->request->query->set('page', 2);

        $response = $this->dumbController->collectionResponse(
            $this->request,
            DumbTableModel::class
        );

        $this->assertSame(3, $response['meta']['total_pages']);
        $this->assertSame(10, count($response['data']));
    }

    public function testCollectionResponseLimit()
    {
        for ($i = 0; $i < 30; $i++) {
            (new DumbTableModel([
                'attr1' => bin2hex(random_bytes(12))
            ]))->insert();
        }

        $this->request->query->set('limit', 5);

        $response = $this->dumbController->collectionResponse(
            $this->request,
            DumbTableModel::class
        );

        $this->assertSame(6, $response['meta']['total_pages']);
        $this->assertSame(5, count($response['data']));
    }

    public function testCollectionResponseSort()
    {
        for ($i = 0; $i < 15; $i++) {
            (new DumbTableModel([
                'attr1' => bin2hex(random_bytes(12)),
                'attr2' => chr(65 + $i)
            ]))->insert();
        }

        $this->request->query->set('sort', 'attr2');
        $response = $this->dumbController->collectionResponse(
            $this->request,
            DumbTableModel::class
        );
        $this->assertSame('A', $response['data'][0]['attr2']);

        $this->request->query->set('sort', '-attr2');
        $response = $this->dumbController->collectionResponse(
            $this->request,
            DumbTableModel::class
        );
        $this->assertSame('O', $response['data'][0]['attr2']);
    }

    public function testCollectionResponseInclude()
    {
        (new DumbTableModel([
            'attr1' => bin2hex(random_bytes(12)),
            'foreign_id' => (new ForeignTableModel())->insert(),
            'other_foreign_id' => (new ForeignTableModel())->insert()
        ]))->insert();

        $this->request->query->set('include', 'foreign');
        $response = $this->dumbController->collectionResponse(
            $this->request,
            DumbTableModel::class
        );
        $this->assertArrayHasKey('foreign', $response['data'][0]);
        $this->assertArrayNotHasKey('other_foreign', $response['data'][0]);

        $this->request->query->set('include', 'foreign,other_foreign');
        $response = $this->dumbController->collectionResponse(
            $this->request,
            DumbTableModel::class
        );
        $this->assertArrayHasKey('other_foreign', $response['data'][0]);
    }

    public function testCollectionResponseFiltersCallback()
    {
        for ($i = 0; $i < 5; $i++) {
            (new DumbTableModel([
                'attr1' => bin2hex(random_bytes(12))
            ]))->insert();
        }

        $attr1 = DumbTableModel::select()->inRandomOrder()->first()->attr1;

        $response = $this->dumbController->collectionResponse(
            $this->request,
            DumbTableModel::class,
            function ($query) use ($attr1) {
                return $query->where('attr1', $attr1);
            }
        );

        $this->assertSame($attr1, $response['data'][0]['attr1']);
    }
}
